package de.mhus.lib.core.config;

import de.mhus.lib.core.MException;
import de.mhus.lib.core.directory.DirectoryNode;
import de.mhus.lib.core.directory.WritableDirectoryNode;
import de.mhus.lib.core.lang.MObject;

/**
 * Use this class to copy a hole config structure. The target should be an empty
 * config node. And it should support creation of properties and sub configs.
 * 
 * The main purpose is to create a config of a specified type, e.g. the source is a XmlConfig or
 * unknown and the target a JsonConfig type.
 * 
 * @author mikehummel
 *
 */
public class ConfigBuilder extends MObject {
	
	public void cloneConfig(DirectoryNode src, WritableDirectoryNode tar) {
		
		preProcess(src,tar);
		
		// copy values
		for (String key : src.getPropertyKeys()) {
			if (accept(src,key)) {
				try {
					tar.setProperty(key, mapProperty(src,key,src.getString(key,null) ));
				} catch (MException e) {
					log().i("property",key,e);
				}
			}
		}
		
		// copy sub configurations
		for (String key : src.getNodeKeys()) {
			for (DirectoryNode srcSub : src.getNodes(key)) {
				if (accept(srcSub)) {
					try {
						WritableDirectoryNode tarSub = tar.createConfig(key);
						cloneConfig(srcSub,tarSub);
					} catch (MException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
				}
			}
		}
		
		postProcess(src,tar);
		
	}
	

	/**
	 * Return true if the config sould be copied to the target
	 * @param src
	 * @return
	 */
	boolean accept(DirectoryNode src) {
		return true;
	}

	/**
	 * Process before cloning of this node.
	 * @param src
	 * @param tar
	 */
	void preProcess(DirectoryNode src, WritableDirectoryNode tar) {
	}

	/**
	 * Process after cloning of the node finished.
	 * @param src
	 * @param tar
	 */
	void postProcess(DirectoryNode src, WritableDirectoryNode tar) {
	}

	/**
	 * You can change the value of the property.
	 * @param src
	 * @param key
	 * @param property
	 * @return
	 */
	String mapProperty(DirectoryNode src, String key, String value) {
		return value;
	}

	/**
	 * Return true if the property can be cloned to the target.
	 * @param src
	 * @param key
	 * @return
	 */
	boolean accept(DirectoryNode src, String key) {
		return true;
	}
		
}
